package seentao.stdev.mobile.base.service;


import java.util.List;
import java.util.Map;

import lombok.SneakyThrows;

import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Example;
import org.springframework.data.jpa.repository.JpaRepository;

import seentao.stdev.mobile.util.BeanUtil;

public abstract class CrudService<VO> {
	
	/**
	 * 根据ID获取对象
	 * @param id
	 * @return
	 */
	public VO get(String id) {
		return getDao().getOne(id);
	}
	
	/**
	 * 根据ID查询对象
	 * @param id
	 * @return
	 */
	public VO find(String id) {
		return getDao().findOne(id);
	}
	
	/**
	 * 根据条件查询单一对象
	 * @param example
	 * @return
	 */
	public VO find(VO example) {
		return getDao().findOne(Example.of(example));
	}
	
	/**
	 * 查询所有对象
	 * @return
	 */
	public List<VO> findAll() {
		return getDao().findAll();
	}
	
	/**
	 * 根据ID查询一组对象
	 * @param ids
	 * @return
	 */
	public List<VO> findAll(List<String> ids) {
		return getDao().findAll(ids);
	}
	
	/**
	 * 根据条件查询一组对象
	 * @param example
	 * @return
	 */
	public List<VO> findAll(VO example) {
		return getDao().findAll(Example.of(example));
	}
	
	//=======================
	
	/**
	 * 查询所有对象的个数
	 * @return
	 */
	public long count() {
		return getDao().count();
	}
	
	/**
	 * 根据条件查询一组对象的个数
	 * @param example
	 * @return
	 */
	public long count(VO example) {
		return getDao().count(Example.of(example));
	}
	
	//=======================
	
	/**
	 * 根据ID判断对象是否存在
	 * @param id
	 * @return
	 */
	public boolean exists(String id) {
		return getDao().exists(id);
	}
	
	/**
	 * 根据条件判断对象是否存在
	 * @param example
	 * @return
	 */
	public boolean exists(VO example) {
		return getDao().exists(Example.of(example));
	}
	
	//=======================
	
	/**
	 * 根据ID查询对象的属性
	 * @param id
	 * @param property
	 * @return
	 */
	public Object getValue(String id, String property) {
		return BeanUtil.getProperty(find(id), property);
	}
	
	/**
	 * 根据条件查询单一对象的属性
	 * @param example
	 * @param property
	 * @return
	 */
	public Object getValue(VO example, String property) {
		return BeanUtil.getProperty(find(example), property);
	}
	
	//=======================
	
	/**
	 * 保存对象
	 * @param vo
	 * @return
	 */
	public VO save(VO vo) {
		return getDao().save(vo);
	}
	
	/**
	 * 保存对象如果不存在
	 * @param vo
	 * @return
	 */
	@SneakyThrows
	public VO saveIfNotExists(VO vo, String... properties) {
		if (properties.length == 0) {
			throw new IllegalArgumentException("");
		}

		VO example = (VO) vo.getClass().newInstance();
		for (String prop : properties) {
			Object value = BeanUtil.getProperty(vo, prop);
			BeanUtil.setProperty(example, prop, value);
		}

		if (!getDao().exists(Example.of(example))) {
			return getDao().save(vo);
		} else {
			VO vo2 = getDao().findOne(Example.of(example));
			BeanUtils.copyProperties(vo2, vo);
			return vo;
		}
	}
	
	/**
	 * 批量保存对象
	 * @param vos
	 * @return
	 */
	public List<VO> save(List<VO> vos) {
		return getDao().save(vos);
	}
	
	//=======================
	
	/**
	 * 批量更新对象的属性
	 * @param vos
	 * @param properties
	 * @return
	 */
	public List<VO> update(List<VO> vos, Map<String, Object> properties) {
		for (VO vo : vos) {
			for (Map.Entry<String, Object> prop : properties.entrySet()) {
				BeanUtil.setProperty(vo, prop.getKey(), prop.getValue());
			}
		}
		return save(vos);
	}
	
	/**
	 * 批量更新某个条件下的对象的属性
	 * @param example
	 * @param properties
	 * @return
	 */
	public List<VO> update(VO example, Map<String, Object> properties) {
		return update(findAll(example), properties);
	}
	
	/**
	 * 根据ID批量更新对象的属性
	 * @param ids
	 * @param properties
	 * @return
	 */
	public List<VO> updateById(List<String> ids, Map<String, Object> properties) {
		return update(findAll(ids), properties);
	}
	
	//=======================
	
	/**
	 * 根据ID删除对象
	 * @param id
	 */
	public void delete(String id) {
		getDao().delete(id);
	}
	
	/**
	 * 删除对象
	 * @param vo
	 */
	public void delete(VO vo) {
		getDao().delete(vo);
	}
	
	/**
	 * 根据ID批量删除对象
	 * @param ids
	 */
	public void deleteAllById(List<String> ids) {
		getDao().delete(getDao().findAll(ids));
	}
	
	/**
	 * 批量删除对象
	 * @param vos
	 */
	public void deleteAll(List<VO> vos) {
		getDao().delete(vos);
	}
	
	//=======================
	
	/**
	 * 清除表
	 */
	public void clear() {
		getDao().deleteAllInBatch();
	}
	
	/**
	 * 更新内存
	 */
	public void flush() {
		getDao().flush();
	}
	
	public abstract JpaRepository<VO, String> getDao();
	
}
